package com.thh.ftp.util;

import com.thh.ftp.config.FtpConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: science-innovation-parent
 * @description: FTP文件服务器工具类
 * @author: thh
 * @create: 2019-12-19 13:45
 */

@Slf4j
public class FTPUtils {



    private static final FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_NT);
    public static final String DATE_TIME_FORMAT_TWO = "yyyy-MM-dd HH:mm";

    static {
        config.setDefaultDateFormatStr(DATE_TIME_FORMAT_TWO);
        config.setServerTimeZoneId("GMT+8");
        config.setServerLanguageCode("zh");
    }

    /**
     * 获取ftp 客户端
     *
     * @param ftpConfig ftp连接对象
     * @return FTPClient ftp客户端
     */
    public static FTPClient getClient(FtpConfig ftpConfig) {
        FTPClient client = new FTPClient();
        client.configure(config);
        try {
            client.connect(ftpConfig.getIp(), ftpConfig.getPort());
            client.enterLocalPassiveMode();

            int replyCode = client.getReplyCode();

            if (FTPReply.isPositiveCompletion(replyCode)) {
                client.login(ftpConfig.getUser(), ftpConfig.getPassword());
                replyCode = client.getReplyCode();
                if (FTPReply.isPositiveCompletion(replyCode)) {
                    return client;
                } else {
                    log. info(String.format("ftp client open faild. replyCode: %d, %s ", replyCode, client.getReplyString()));
                    client.disconnect();
                    return null;
                }
            } else {
                log.info(String.format("ftp client open faild. replyCode: %d, %s ", replyCode, client.getReplyString()));
                client.disconnect();
                return null;
            }
        } catch (IOException e) {
            log.info("ftp client open faild" + e);
            return null;
        }
    }

    /**
     * ftp 连接断开C
     *
     * @param client ftp 客户端
     */
    public static void close(FTPClient client) {
        try {
            if (!client.isConnected()) {
                client.disconnect();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * ftp上传单个文件
     *
     * @param ftpClient ftp客户端
     * @param file      文件流
     * @param directory 目标地址
     * @param fileName   保存后名字
     * @return result   是否成功
     */
    //ftp://192.168.17.110
    public static boolean upload(FTPClient ftpClient, File file, String directory, String fileName) {
        boolean result = false;
        try {
            // 设置上传目录
            boolean change = ftpClient.changeWorkingDirectory(directory);
            //跳转到文件上传的路径
            //分割路径 第一步
            List<String> list = getPathList(directory);
            //循环遍历创建路径
            for (int i = 0; i < list.size(); i++) {
                if (!ftpClient.changeWorkingDirectory(list.get(i))) {//若路径未存在则创建路径
                    if (!ftpClient.makeDirectory(list.get(i))) {//若路径创建失败则不再继续处理
                        log.info("create dir fail --> " + list.get(i));
                        return false;
                    } else {
                        if (i == list.size() - 1) {
                            ftpClient.changeWorkingDirectory(list.get(i));
                        }
                    }
                }
            }
            ftpClient.setBufferSize(1024);
            ftpClient.setControlEncoding("gbk");
            //获取文件流
            InputStream inputStream = new FileInputStream(file);
            //获取文件全名

            // 设置文件类型（二进制）
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //解决了上传不了中文的问题 先把文件名称转成byte 然后转成iso-8859-1
            result = ftpClient.storeFile(new String(fileName.getBytes("GBK"), "iso-8859-1"), inputStream);
        } catch (NumberFormatException e) {
            log.info("FTP端口配置错误:不是数字:");
            e.printStackTrace();
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.toString());
        }
        return result;
    }


    /**
     * 获取ftp的文件流
     * @param ftpClient ftp客户端
     * @param directory 目标地址
     * @return InputStream 文件流
     */
    public static byte[] download(FTPClient ftpClient, String directory) {
        InputStream is = null;
        byte[] body = null;
        FileOutputStream out = null;
        try {
            //获取ftp上的文件
            is = ftpClient.retrieveFileStream(directory);
            body = IOUtils.toByteArray(is);
            is.read(body);
            is.close();
            return body;
        } catch (Exception e) {
            log.info(e.toString());
        }
        return body;
    }

    /**
     * 获取ftp的InputStream
     * @param ftpClient ftp客户端
     * @param directory 目标地址
     * @return InputStream 文件流
     */
    public static InputStream getInputStream(FTPClient ftpClient, String directory) {
        InputStream is = null;
        try {
            //获取ftp上的文件
            is = ftpClient.retrieveFileStream(new String(directory.getBytes("gbk"), "ISO-8859-1"));
            return is;
        } catch (Exception e) {
            log.info(e.toString());
        }
        return is;
    }

    public static boolean delete(FTPClient ftpClient, String directory) {

        InputStream is = null;
        String pathname = directory.substring(0,directory.lastIndexOf("/"));
        String filename = directory.substring(directory.lastIndexOf("/")+1);

        try {
            //判断文件是否存在
            is = ftpClient.retrieveFileStream(directory);
            //不存在直接返回true
            if(is==null){
                return true;
            }else{
                is.close();

                ftpClient.changeWorkingDirectory(pathname);
                ftpClient.dele(filename);
                ftpClient.logout();

                return true;
            }
        } catch (Exception e) {
            log.info(e.toString());
        }
        return false;
    }
    //分割路径
    public static List<String> getPathList(String path) {
        String[] dirs = path.split("/");
        List<String> list = new ArrayList<>();
        String pathname = "";
        for (String str : dirs) {
            if (StringUtils.isEmpty(str)) {
                continue;
            }
            pathname = pathname + "/" + str;
            list.add(pathname);
        }
        return list;
    }




}
